package cn.wit.sst.view;

import java.util.List;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Controller;

import cn.wit.sst.domain.College;
import cn.wit.sst.domain.Major;
import cn.wit.sst.dto.MajorQuery;
import cn.wit.sst.dto.ScoreRankDto;
import cn.wit.sst.service.MajorService;
import cn.wit.sst.utils.AppCache;
import cn.wit.sst.utils.Dialogs;
import io.reactivex.Observable;
import io.reactivex.rxjavafx.schedulers.JavaFxScheduler;
import io.reactivex.schedulers.Schedulers;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Spinner;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.util.StringConverter;

@Controller
public class MajorController {
	private static final Logger logger = LoggerFactory.getLogger(StudentController.class);
	@FXML ChoiceBox<College> choiceCollege;
	@FXML ChoiceBox<Major> choiceMajor;
	@FXML Spinner<Integer> spinnerYear;
	@FXML ToggleGroup grpGrade;
	@FXML ToggleGroup grpSemester;

	@FXML RadioButton radioGrade1;
	@FXML RadioButton radioGrade2;
	@FXML RadioButton radioGrade3;
	@FXML RadioButton radioGrade4;
	@FXML RadioButton radioSemester1;
	@FXML RadioButton radioSemester2;
	@FXML VBox chartContainer;

	@Autowired
	AppCache cache;

	@Autowired
	MajorService clazzService;
	@FXML
	public void initialize() {
		radioGrade1.setUserData(0);
		radioGrade2.setUserData(1);
		radioGrade3.setUserData(2);
		radioGrade4.setUserData(3);

		radioSemester1.setUserData(1);
		radioSemester2.setUserData(2);

		choiceCollege.setConverter(new StringConverter<College>() {
			@Override
			public String toString(College object) {
				return object.getName();
			}

			@Override
			public College fromString(String string) {
				return null;
			}
		});
		// 选中学院时、查询对应的专业
		choiceCollege.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
			System.out.println(newValue.getId());
			Observable.just(newValue.getId())
				.observeOn(Schedulers.computation())
				.map(id -> clazzService.selectMajorByCollegeId(id))
				.observeOn(JavaFxScheduler.platform())
				.subscribe(items -> {
					choiceMajor.getItems().clear();
					choiceMajor.getItems().addAll(items);
				});
		});

		choiceMajor.setConverter(new StringConverter<Major>() {
			@Override
			public String toString(Major object) {
				return object.getName();
			}

			@Override
			public Major fromString(String string) {
				return null;
			}
		});
	}

	@EventListener
	public void onCacheReadyEvent(AppCache.CacheReadyEvent event) {
		choiceCollege.getItems().addAll(cache.getColleges());
	}

	@FXML public void handSearchAction(ActionEvent event) {
		chartContainer.getChildren().clear();
		Observable.just(getQuery())
			.observeOn(Schedulers.computation())
			.map(q -> clazzService.search(q))
			.observeOn(JavaFxScheduler.platform())
			.subscribe(items -> {
				items.entrySet().forEach(e -> showLineChart(e));
			});
	}

    private void showLineChart(Entry<Long, List<ScoreRankDto>> entry) {
		LineChart<String, Number> chart;
		CategoryAxis xAxis;
		NumberAxis yAxis;

		xAxis = new CategoryAxis();
		xAxis.setTickLabelRotation(60d);
		yAxis = new NumberAxis();

		chart = new LineChart<>(xAxis, yAxis);
		chart.getStyleClass().add("score-chart");

		// 课程名作为标题
		chart.setTitle(cache.getCourse(entry.getKey()).getName());
		chart.setLegendVisible(false);
		chart.setHorizontalGridLinesVisible(false);
		chart.setVerticalGridLinesVisible(false);
		chart.setPrefWidth(entry.getValue().size() * 48d);

		yAxis.setLabel("分数");

		// add starting data
		XYChart.Series<String, Number> series = new XYChart.Series<>();
		entry.getValue().forEach(score -> {
			Data<String, Number> data = new XYChart.Data<String, Number>(score.getStudent(), score.getScore());
			Node node = createNodeLabel(score.getRank());

			String tooltip = String.format("%s (%2.0f)", score.getStudent(), score.getScore());
			Tooltip.install(node, Dialogs.tooltip(tooltip));
			data.setNode(node);
			series.getData().add(data);
        });

		chart.getData().add(series);

		chartContainer.getChildren().add(chart);
	}

	private Node createNodeLabel(int rank) {
		StackPane stackPane = new StackPane();

		Circle circle = new Circle(8d);
		circle.setStrokeWidth(1d);
		circle.setStroke(Color.DARKGRAY);
		circle.setFill(Color.WHITE);
		stackPane.getChildren().add(circle);

		Label label = new Label(rank + "");
		label.setStyle("-fx-font-size: 8; -fx-font-weight: bold;");

		label.setTextFill(Color.FORESTGREEN);

		stackPane.getChildren().add(label);
		return stackPane;
	}


	private MajorQuery getQuery() {
    	Major item = choiceMajor.getSelectionModel().getSelectedItem();
    	if (item == null) {
    		Dialogs.alert("请选中专业！");
    		return null;
    	}

    	Integer year = spinnerYear.getValue();
    	if (year == null) {
    		Dialogs.alert("请输入学年！");
    		return null;
    	}

    	int grade = (int) grpGrade.getSelectedToggle().getUserData();
    	int semester = (int) grpSemester.getSelectedToggle().getUserData();
    	logger.info("查询条件：学年【{}】，学期【{}】", grade, semester);

    	MajorQuery query = new MajorQuery();
    	query.setMid(item.getId());
    	query.setGrade(grade);
    	query.setSemester(semester);
    	query.setYear(Integer.valueOf(year));

    	return query;
    }
}
